﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;

namespace plug_uconv
{
    class xmlreader
    {
        private List<Unit> Engine;
        private XmlDocument xml;
        private XmlNode rootnode;
        private bool ok;

        private double parsenum(string s)
        {
            string cnv = null;
            if (CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator == ",") cnv = s.Replace('.', ',');
            else cnv = s;
            return Convert.ToDouble(cnv);
        }

        public xmlreader()
        {
            this.Engine = new List<Unit>();
            this.xml = new XmlDocument();

            this.xml.LoadXml(plug_uconv.Properties.Resources.engine);
            this.ok = false;
            for (int i = 0; i < xml.ChildNodes.Count; i++)
            {
                if (xml.ChildNodes[i].Name == "uconv")
                {
                    this.rootnode = xml.ChildNodes[i];
                    this.ok = true;
                    break;
                }
            }
            if (!ok) throw new Exception("Error reading unit conversion table, No root node foud");
            
            ok = false;

            foreach (XmlNode category in rootnode.ChildNodes)
            {
                if (category.Name == "category")
                {
                    this.Engine.AddRange(this.GetUnits(category));
                    ok = true;
                }
            }

            if (!ok) throw new Exception("No category elements found in the conversion table");
        }

        private Unit[] GetUnits(XmlNode parent)
        {
            List<Unit> ret = new List<Unit>();
            foreach (XmlNode child in parent.ChildNodes)
            {
                if (child.Name == "unit")
                {
                    Unit returnval = new Unit();
                    returnval.Ratio = this.parsenum(child.InnerText);
                    returnval.Category = parent.Attributes["name"].InnerText;
                    returnval.Action = (convAction)Enum.Parse(typeof(convAction), child.Attributes["action"].InnerText);
                    returnval.Name = child.Attributes["name"].InnerText;
                    returnval.sName = child.Attributes["sname"].InnerText;
                    ret.Add(returnval);
                }
            }
            return ret.ToArray();
        }

        public Dictionary<string, string> GetAutoCompItems()
        {
            Dictionary<string, string> ret = new Dictionary<string, string>();
            for (int i = 0; i < this.Count; i++)
            {
                if (ret.ContainsKey(this[i].Category)) ret[this[i].Category] += this[i].Name + ";";
                else ret.Add(this[i].Category, this[i].Name+";");
            }
            return ret;
        }

        public int Count
        {
            get { return Engine.Count; }
        }

        public Unit this[int i]
        {
            get { return this.Engine[i]; }
        }

        public Unit this[string category, string name]
        {
            get
            {
                Unit returnval = new Unit();
                foreach (Unit un in this.Engine)
                {
                    if (un.Category == category && un.Name == name)
                    {
                        returnval = un;
                        break;
                    }
                }
                return returnval;
            }
        }

        public Unit this[string sname]
        {
            get
            {
                Unit returnval = new Unit();
                foreach (Unit un in this.Engine)
                {
                    if (un.sName == sname || un.Name == sname)
                    {
                        returnval = un;
                        break;
                    }
                }
                return returnval;
            }
        }

        public Unit getStandard(string category)
        {
            Unit res = new Unit();
            foreach (Unit u in this.Engine)
            {
                if (u.Category == category && u.Action == convAction.none)
                {
                    res = u;
                    break;
                }
            }
            return res;
        }

        public double Conv2Std(Unit u, double value)
        {
            double res;
            if (u.Action == convAction.multiply) res = value / u.Ratio;
            else if (u.Action == convAction.add) res = value - u.Ratio;
            else if (u.Action == convAction.divide) res = value * u.Ratio;
            else if (u.Action == convAction.subtract) res = value + u.Ratio;
            else res = value;
            return res;
        }

        public double Conv2unit(Unit u, double stdval)
        {
            double res;
            if (u.Action == convAction.multiply) res = stdval * u.Ratio;
            else if (u.Action == convAction.add) res = stdval + u.Ratio;
            else if (u.Action == convAction.subtract) res = stdval - u.Ratio;
            else if (u.Action == convAction.divide) res = stdval / u.Ratio;
            else res = stdval;
            return res;
        }

        public bool CanConvert(Unit src, Unit dest)
        {
            if (src.Category == dest.Category) return true;
            else return false;
        }
    }
}
